import { defineStore } from "pinia";
import type { Log, LogFilter } from '@/env'
import { reactive } from "vue";
import { getMylogs, getPublics } from "../api/log";
import dayjs from "dayjs";
import { computed } from "vue";

/**
 * 直接查全部的数据项
 */
export interface AllStore {
	/**
	 * 存储所有数据
	 */
	listAll : Log[]
	/**
	 * 加载状态
	 */
	loading : boolean
	/**
	 * 获取所有mylog，会直接覆盖listAll
	 */
	getLogs : () => Promise<void>
}

/**
 * 要分页查询需要的数据项
 */
export interface PageStore {
	/**
	 * 真正显示的数据
	 */
	list : Log[]
	/**
	 * 请求参数
	 */
	params : { skip : number; limit : number }
	/**
	 * 加载状态
	 */
	loading : boolean
	/**
	 * 是否还有数据
	 */
	noMore : boolean
	/**
	 * 分页添加log
	 */
	addLogs : () => Promise<void>
}

// mylog的类型
export interface MylogStore extends AllStore, PageStore {
	/**
	 * 通过参数显示的数据
	 */
	// list: Log[]
	/**
	 * 存储所有数据
	 */
	listAll : Log[]
	/**
	 * 过滤器
	 */
	filter : LogFilter | undefined
	/**
	 * 经过筛选后的Log列表，计数属性
	 */
	listFilter : Log[]
	/**
	 * 每次调用都会重置params，重新筛选
	 * @param filter 过滤器
	 */
	setFilter : (filter ?: LogFilter) => void
}

export const useLogStore = defineStore('log', () => {
	// 主页的logs
	const home = reactive<PageStore>({
		list: [],
		params: { skip: 0, limit: 20 },
		loading: true,
		noMore: false,
		addLogs: async () => {
			if (home.noMore) return
			home.loading = true
			const data = await getPublics(home.params)
			if (data.length < home.params.limit) home.noMore = true
			data.forEach(handleLog)
			home.list.push(...data)
			home.params.skip += home.params.limit
			home.loading = false
		},
	})

	/**
	 * all在获取时就要排序，插入时就要插入到应有位置，避免sort耗费性能
	 * 后端传来的数据就是排好的，前端插入逻辑尽量不用sort，编辑逻辑先删再插入
	 * 删除逻辑也避免使用filter
	 */
	const mylog : MylogStore = reactive({
		list: computed<Log[]>(() => mylog.listFilter.slice(0, mylog.params.skip)),
		listAll: [],
		filter: undefined,
		listFilter: computed<Log[]>(() =>
			mylog.listAll.filter(log => filteLog(log, mylog.filter))
		), // 由all筛选而来
		// 每次调用都会重置params，重新筛选
		setFilter: (filter ?: LogFilter) => {
			mylog.params.skip = 0
			mylog.filter = filter
			mylog.addLogs()
		},
		params: { skip: 0, limit: 10 },
		loading: true,
		noMore: false,
		addLogs: async () => {
			if (mylog.params.skip > mylog.listFilter.length) {
				mylog.noMore = true
				return
			}
			mylog.params.skip += mylog.params.limit
		},
		getLogs: async () => {
			mylog.loading = true
			const logs = await getMylogs({})
			logs.forEach(handleLog)
			mylog.listAll = logs
			mylog.addLogs() // 加载完成后立即加载几个数据
			mylog.loading = false
		},
	})

	return { home, mylog }
})

export default useLogStore

/**
 * 处理单个Log，直接操作参数
 * 1. 以前要转json,现在不用了
 * 2. 时间要处理, 用dayjs转
 */
export const handleLog = (log : Log) : void => {
	log.id = String(log.id)
	log.logtime = dayjs(log.logtime)
	log.sendtime = dayjs(log.sendtime)
	for (let i in log.imgs) {
		if (log.imgs[i].startsWith('http://'))
			log.imgs[i] = log.imgs[i].replace('http://', 'https://')
	}
}

/**
 * 传入一个log，返回布尔值
 * @param log Log对象
 * @param filter 过滤器对象
 * @return 为真就是满足，false就是不满足
 */
export const filteLog = (log : Log, filter ?: LogFilter) : boolean => {
	// 参二传入null，直接返回true
	if (!filter) return true

	// 记录状态
	if (filter.type !== '' && log.type != filter.type) return false

	// 时间限制，包含两头
	if (filter.timeLimit[0] && log.logtime.diff(dayjs(filter.timeLimit[0])) < 0)
		return false
	if (
		filter.timeLimit[1] &&
		log.logtime.diff(dayjs(filter.timeLimit[1])) > 86400000
	)
		return false

	// 排除
	if (filter.exclude.includes(log.id!)) return false

	const includes = (filter : string[], logV : string[], isOr : boolean) => { }

	if (filter.content.include.length) {
		const f = filter.content.isOr
			? filter.content.include.some(c => log.content.includes(c))
			: filter.content.include.every(c => log.content.includes(c))
		if (f) {
			if (filter.isOrAll) return true
		} else {
			return false
		}
	}

	if (filter.people.include.length) {
		const f = filter.people.isOr
			? filter.people.include.some(c => log.people!.includes(c))
			: filter.people.include.every(c => log.people!.includes(c))
		if (f) {
			if (filter.isOrAll) return true
		} else {
			return false
		}
	}

	if (filter.tags.include.length) {
		const f = filter.tags.isOr
			? filter.tags.include.some(c => log.tags!.includes(c))
			: filter.tags.include.every(c => log.tags!.includes(c))
		if (f) {
			if (filter.isOrAll) return true
		} else {
			return false
		}
	}

	return true
}